# vim:ft=sh

# al-include.cfg - Variables and functions commonly used in custom scripts

# Copyright (C) 2012 Philip Newborough <corenominal@corenominal.org>
# Copyright (C) 2013 Aleks-Daniel Jakimenko
# Copyright (C) 2015-2016  John Crawley <john@bunsenlabs.org>
# Copyright (C) 2016  xaos52 <xaos52@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# These functions can be used in user scripts too, by first sourcing this file, eg:
# AL_COMMON_LIBDIR='/usr/lib/archlabs/common'
# if ! . "$AL_COMMON_LIBDIR/al-include.cfg" 2> /dev/null; then
#     echo $"Error: Failed to locate al-include.cfg in $AL_COMMON_LIBDIR" >&2
#     exit 1
# fi

# NOTE: Do not source this file in non-Bash shell scripts.
# It uses some "bashisms".

########################################################################
# Functions to generate Openbox menus.

menuStart() {
    echo '    <openbox_pipe_menu>'
}

# Usage: menuItem label command
menuItem() {
    echo "        <item label=\"$(OBlabelEscape "$(XMLescape "$1")")\">"
    echo '          <action name="Execute">'
    echo "            <command>$(XMLescape "$2")</command>"
    echo '          </action>'
    echo '        </item>'
}

# Usage: menuSeparator [label]
menuSeparator() {
    if [[ ${1-} ]]; then
        echo "        <separator label=\"$(OBlabelEscape "$(XMLescape "$1")")\"/>"
    else
        echo '        <separator/>'
    fi
}

# Usage menuSubmenu id label # http://openbox.org/wiki/Help:Menus
menuSubmenu() {
    echo "    <menu id=\"$(XMLescape "$1")\" label=\"$(OBlabelEscape "$(XMLescape "$2")")\">"
}

menuSubmenuEnd() {
    echo '    </menu>'
}

menuEnd() {
    echo '    </openbox_pipe_menu>'
}

# escape special characters
XMLescape() {
    local string="${1//&/&amp;}"
    string="${string//</&lt;}"
    string="${string//>/&gt;}"
    string="${string//\"/&quot;}"
    string="${string//\'/&apos;}"
    printf '%s' "$string"
}

OBlabelEscape() {
    printf '%s' "${1//_/__}"
}

########################################################################

# rerun script in terminal if necessary
# Usage: terminalCheck [ -T title ] [arguments...]
terminalCheck() {
    if ! [[ -t 0 && -t 1 && -t 2 ]]; then # not attached to terminal
        if [[ -n $DISPLAY ]]; then # running X
            if [[ ${1-} = '-T' ]]; then
                local title=${2-}
                shift 2
                exec exo-open --launch TerminalEmulator -T "$title" -e "$0" "$@"
            else
                exec exo-open --launch TerminalEmulator -e "$0" "$@"
            fi
        else
            echo "$0: no terminal" >&2
            exit 1
        fi
    fi
}

# Usage: createFlag filename
createFlag() {
    mkdir -p "$HOME/.config/archlabs"
    touch "$HOME/.config/archlabs/$1"
}

# Check the connection by downloading a file from ftp.debian.org. No disk space used.
# Usage: connectiontest [attempts]
# If attempt count is not specified or 0, then it will loop forever and exit(!) your main program with 1 exit status.
connectiontest() {
    local TEXT_CHECKING='Checking internet connection...'
    local TEXT_FAILED='Internet connection test failed!'
    local TEXT_ASK_RETRY=$'\n\nThis script requires a working internet connection. Please configure your internet connection, then hit "Enter" to continue, else hit "q" to quit.'
    local TEXT_ABORT='Script aborted.'
    local TEXT_OK='Internet connection test passed!'

    local -i i attempts=${1-0}
    for (( i=0; i < attempts || attempts == 0; i++ )); do
        say "$TEXT_CHECKING"
        if wget -O - 'http://ftp.debian.org/debian/README' &> /dev/null; then
            say "$TEXT_OK" 1
            return 0
        fi
        say "$TEXT_FAILED"
        if (( i == attempts - 1 )); then # if last attempt
            return 1
        elif prompt "$TEXT_ASK_RETRY" Q; then # if user wants to quit
            say "$TEXT_ABORT" 2
            (( attempts == 0 )) && exit 1 || return 1
        fi
        tput clear
    done
}

# Check for availability of commands used in script.
# Usage: declareDependencies command [command...]
declareDependencies(){
    local missing_commands=() i=
    for i in "$@"; do
        hash "$i" 2>/dev/null || missing_commands+=(" $i")
    done
    [[ ${missing_commands[0]} ]] && errorExit "This script requires the following commands: ${missing_commands[*]}
Please install the packages containing the missing commands
and rerun the script."
}

########################################################################
# User interface functions.

# Usage: say text [delayAfterText|pause]
say() {
    local width=$(tput cols 2>/dev/tty)
    fold -s -w $((width - 3)) <<< "${1-}" | sed 's/^/  /' # wraps text nicely and adds two leading spaces
    if [[ ${2-} = 'pause' ]]; then
        echo $'\nPress any key to continue.'
        read -srn1
    else
        sleep "${2:-0}"
    fi
}

# Usage errorExit message [details]
errorExit() {
    say $'\n'"$1"$'\n' '1' >&2
    [[ ${2-} ]] && {
        while true; do
            local REPLY
            read -rn1 -p '  Press "d" for details (q to quit) '
            [[ ${REPLY^} = Q ]] && exit 1
            [[ ${REPLY^} = D ]] && {
                echo $'\n\n'
                tput setaf 1
                echo "$2" >&2
                tput sgr0
                say "
Would you like to quit now, or continue anyway?
(Be careful!)
Press \"q\" to quit, \"c\" to continue:
"
                read -r
                [[ ${REPLY^} = Q ]] && exit 1
                [[ ${REPLY^} = C ]] && return 0
            }
        done
    }
    say 'Press any key to exit.'
    read -srn1
    exit 1
}

# Usage: prompt text [ Y | N | Q | <string> ]
prompt() {
    local answer prompt default
    if [[ ${2-} && ${2^} = Q ]]; then
        while true; do
            read -srn1 -p "$1" answer
            echo
            [[ ${answer^} = Q ]] && return 0
            [[ ! $answer ]] && return 1
        done
    fi

    if [[ ! ${2-} || ${2^} = Y ]]; then
        prompt='Y/n'
        default='Y'
    elif [[ ${2^} = N ]]; then
        prompt='y/N'
        default='N'
    else
        prompt=
        default=
    fi

    while true; do
        read -r -p "$1 ${prompt:+[$prompt] }" answer

        if [[ ! $prompt && ! $default ]]; then
            if [[ $answer = ${2-} ]]; then
                echo
                return 0
            elif [[ ${answer^} = Q ]]; then
                echo
                return 1
            else
                continue
            fi
        fi

        [[ ! $answer ]] &&
            answer=$default

        if [[ ${answer^} = Y || ${answer^^} = YES ]]; then
            echo
            return 0
        elif [[ ${answer^} = N || ${answer^^} = NO ]]; then
            echo
            return 1
        fi
    done
}
